package org.testfire.realm.control.agent.ResponseHandlers;

import java.sql.Timestamp;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.Status;
import javax.transaction.UserTransaction;
import org.apache.log4j.Logger;
import org.testfire.realm.control.agent.AgentManager;
import org.testfire.realm.control.agent.event.AgentAvailableEvent;
import org.testfire.realm.control.testfire.TestsetBean;
import org.testfire.realm.control.testfire.TestsetResultBean;
import org.testfire.realm.model.entities.User;
import org.testfire.realm.model.entities.testfire.*;
import org.testfire.realm.util.S;

/**
 * Created by IntelliJ IDEA.
 * User: granum
 * Date: Sep 14, 2007
 * Time: 12:18:42 PM
 */
public class TestsetResponseHandler
{
    // Inject the lgsrealm entity manager, as defined in the persistence.xml file.
    @PersistenceContext(unitName = "testfire")
    EntityManager em;

    @Resource
    private UserTransaction utx;

    TestsetBean testsetBean;

    Logger log = Logger.getLogger( TestsetResponseHandler.class );

    private TestsetResultBean testsetResultBean;

    public TestsetResponseHandler()
    {

    }

    public void perform( User user, final HttpServletRequest request )
    {

        try
        {
            log.info( " Attempting to set testset response from agent... " );
            utx.begin();
            String agentIdString = request.getParameter( "id" );
            Integer agentId = Integer.parseInt( agentIdString );
            AgentEntity agent = em.merge( em.find( AgentEntity.class, agentId ) );

            agent.setHastestset( null );

            String name = request.getParameter( "testset_name" );
            String testsetIdParam = request.getParameter( "testset_id" );
            if ( S.empty( testsetIdParam ) )
            {
                log.info( "Invalid testset ID, aborting." );
                return;
            }
            Integer testset_id = Integer.valueOf( testsetIdParam );

            String testsetResultIdParam = request.getParameter( "testsetResult_id" );
            if ( S.empty( testsetResultIdParam ) )
            {
                log.info( "Invalid testsetResult ID, aborting." );
                return;
            }
            Integer testsetResult_id = Integer.valueOf( testsetResultIdParam );
            String errMsg = request.getParameter( "errormessage" );

            String runtimeParam = request.getParameter( "runtime" );
            runtimeParam = S.empty( runtimeParam ) ? "0" : runtimeParam;
            Integer runtime = Integer.valueOf( runtimeParam );

            String failureCountParam = request.getParameter( "failurecount" );
            failureCountParam = S.empty( failureCountParam ) ? "-1" : failureCountParam;
            Integer failureCount = Integer.valueOf( failureCountParam );

            log.info( "\tReceived testset results for testset: " + name
                + "\n\t Testset id " + testset_id
                + "\n\t TestsetResult id " + testsetResult_id
                + "\n\t Error Message: " + errMsg
                + "\n\t Runtime: " + runtime
                + "\n\t Failure Count: " + failureCount
            );

            TestsetEntity testset = em.merge( testsetBean.getTestset( testset_id ) );
            TestsetResultEntity result = em.merge( testsetResultBean.getTestsetResult( testsetResult_id ) );

            result.setFinished( new Timestamp( System.currentTimeMillis() ) );

            if ( !S.empty( errMsg ) )
            {
                result.setErrorMessage( errMsg );
                result.setStatuscode( ResultStatus.ERROR_COULD_NOT_EXECUTE_TESTS );
            }
            else
            {

                if(failureCount > 0)
                {
                    result.setErrorMessage( "Testset ran with failures." );
                    result.setStatuscode( ResultStatus.RAN_WITH_FAILURES);
                }
                else{
                    result.setErrorMessage( "" );
                    result.setStatuscode( ResultStatus.SUCCESS );
                }
            }
            result.setRunTime( runtime );
            result.setFailureCount( failureCount );

            if ( failureCount != 0 )
            {
                for ( int i = 0; i < failureCount; i++ )
                {
                    String key = "failure_" + i + "_";
                    String desc = request.getParameter( key + "description" );
                    String testMessage = request.getParameter( key + "message" );
                    String testTrace = request.getParameter( key + "trace" );
                    String testHeader = request.getParameter( key + "header" );
                    String testName = testHeader.substring( 0, testHeader.indexOf( "(" ) );

                    TestResultsEntity testResult = new TestResultsEntity();
                    testResult.setTestsetResult( result );

                    log.info( "Failure " + i + " description: " + desc );
                    testResult.setErrorMessage( testMessage );
                    testResult.setErrorTrace( testTrace );
                    TestEntity test = testsetBean.getTest( testset_id, testName );
                    testResult.setTest( test );
                    testResult.setRunDuration( 0 );
                    testResult.setStatuscode( ResultStatus.RAN_WITH_FAILURES );
                    em.persist( testResult );
                }
                em.flush();
                log.info( "Commiting changes made to TestsetResult to the DB" );
                utx.commit();
                log.info( "Informing system that an agent has come available." );
                new AgentManager().fireAgentHasComeAvailableEvent( new AgentAvailableEvent( agent ) );
            }
        }
        catch ( Exception ex )
        {
            log.error( "Could not commit changes made to TestsetResult sent from agent.", ex );
            try
            {
                if ( utx.getStatus() == Status.STATUS_ACTIVE )
                {
                    utx.rollback();
                }
            }
            catch ( Exception ex2 )
            {
                log.error( "Could not rollback transaction.", ex2 );

            }
        }
       


    }

    public void setTestsetBean( TestsetBean testsetBean )
    {
        this.testsetBean = testsetBean;
    }

    public void setTestsetResultBean( TestsetResultBean testsetResultBean )
    {
        this.testsetResultBean = testsetResultBean;
    }
}
